/*
 * JTalkerClientChatWindow.java
 *
 * Created on 22. Dezember 2005, 11:25
 */

package info.chrm.jtalker;

import info.chrm.helper.*;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
import java.util.regex.*;

import java.beans.PropertyChangeListener;
import javax.swing.plaf.ActionMapUIResource;

/**
 *
 * @author  chrmac@gmx.de
 */
public class JTalkerFrontChat extends javax.swing.JFrame implements Action, JTalkerClientCommandInterface {

    private JTalkerClientFront parent = null;
    private JTalkerClient.MemberData member = null;
    private UpdateTimer ut = null;
    private ArrayList historyList = new ArrayList();    // List of Strings
    private int historyPosition = 0;                    // 0: last input
    private static final String ownMessageMarker = "<<<<<ME>>>>>";
    private int textAreaStyle = 0;                      // How to format the messages?
    private MemberListModel memberListModel = null;     // Chatroom users Model for JList
    private String [] chatRoomUsers = {"Loading..."};             // TODO: Fill this array!
    private boolean isChatRoom = false;
    
    /** C'tor */
    public JTalkerFrontChat(JTalkerClientFront _parent, JTalkerClient.MemberData _member) {
        this.parent = _parent;
	this.member = _member;

        this.initComponents();        
        this.initShortcuts();    
        this.jTextAreaInput.requestFocus();

	if(this.member.type.equals(JTalkerParser.USER_TYPE_CHATROOM)) {
            try {
               this.isChatRoom = true;
               this.textAreaStyle = 1;
               this.memberListModel = new MemberListModel();
               this.jList2.setModel(this.memberListModel);
               this.jPanel4.setVisible(true);
               this.jLabel1.setText("Chatroom: " + _member.short_name + " @ " + _member.ip);
            } catch (Exception _e) {
                _e.printStackTrace();
            } 
        } else {
           this.jPanel4.setVisible(false);
           this.jLabel1.setText("Chat with " + _member.short_name + " @ " + _member.ip);
        }
        
        this.setLocationRelativeTo(null);
        this.setTitle(_member.short_name);
        this.parent.theClient.registerForCommandResponse(this);

        // Init Timer for updating the Chat-Window
	ut = new UpdateTimer(this);
	ut.start();

	// Overwrite text and background colors
        this.jEditorPaneMain.setBackground(Color.decode(_parent.theClient.guiBgColor));
        this.jEditorPaneMain.setForeground(Color.decode(_parent.theClient.guiTextColor));    
    }
    
    public void actionPerformed(ActionEvent _e) {
        this.sendMessage();
    }       
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {
        jToolBarButtons = new javax.swing.JToolBar();
        jButtonSend_3 = new javax.swing.JButton();
        jButtonSendFile = new javax.swing.JButton();
        jButtonClear = new javax.swing.JButton();
        jButtonView = new javax.swing.JButton();
        jPanel1 = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jPanelHistoryButtons = new javax.swing.JPanel();
        jButtonHistoryUp = new javax.swing.JButton();
        jButtonHistoryDown = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        jTextAreaInput = new javax.swing.JTextArea();
        //jTextAreaInput = new javax.swing.JEditorPane("text/plain", "");
        jPanel4 = new javax.swing.JPanel();
        jScrollPane4 = new javax.swing.JScrollPane();
        jList2 = new javax.swing.JList();
        jScrollPane1 = new javax.swing.JScrollPane();
        jEditorPaneMain = new javax.swing.JEditorPane("text/html; charset=UTF-8", null);
	jEditorPaneMain.setEditable(false);
        ClassLoader cl = ResourceAnchor.class.getClassLoader();

        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                exitForm(evt);
            }
        });

        jEditorPaneMain.addHyperlinkListener(new javax.swing.event.HyperlinkListener() {
            public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) {
                hyperlinkUpdateEvent(evt);
            }
        });
       
        // Plain buttons 
        jToolBarButtons.setRollover(true);
        
        jButtonSend_3.setText("Send Msg.");
        jButtonSend_3.setIcon(new ImageIcon(cl.getResource("icons/mail_send.png")));
        jButtonSend_3.setToolTipText("Send message now (Ctrl+ENTER)");
	jButtonSend_3.setMargin(new java.awt.Insets(1, 2, 1, 2));
        jButtonSend_3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sendMessage();
            }
        });
        jToolBarButtons.add(jButtonSend_3);
        

        jButtonSendFile.setText("Send File");
        jButtonSendFile.setIcon(new ImageIcon(cl.getResource("icons/file_send.png")));
        jButtonSendFile.setToolTipText("Send File");
	jButtonSendFile.setMargin(new java.awt.Insets(1, 2, 1, 2));
        jButtonSendFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sendFile();
            }
        });
        jToolBarButtons.add(jButtonSendFile);
        jToolBarButtons.addSeparator();

        jButtonClear.setIcon(new ImageIcon(cl.getResource("icons/editdelete.png")));
        jButtonClear.setToolTipText("Clear history");
	jButtonClear.setMargin(new java.awt.Insets(1, 2, 1, 2));
        jButtonClear.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                clearHistory();
            }
        });
        jToolBarButtons.add(jButtonClear);

        jButtonView.setIcon(new ImageIcon(cl.getResource("icons/toggle_view.png")));
        jButtonView.setToolTipText("Toggle View");
	jButtonView.setMargin(new java.awt.Insets(1, 2, 1, 2));
        jButtonView.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                toggleView();
            }
        });
        
        jToolBarButtons.add(jButtonView);

        getContentPane().add(jToolBarButtons, java.awt.BorderLayout.NORTH);

        jPanel1.setLayout(new java.awt.BorderLayout());

        jPanel1.setBackground(new java.awt.Color(102, 102, 102));
        jPanel2.setLayout(new java.awt.BorderLayout());

        jPanel2.setPreferredSize(new java.awt.Dimension(400, 85));
        jLabel1.setText("Status");
        jLabel1.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        jPanel2.add(jLabel1, java.awt.BorderLayout.SOUTH);

        jPanelHistoryButtons.setLayout(new java.awt.GridLayout(2, 1));

        jPanelHistoryButtons.setPreferredSize(new java.awt.Dimension(50, 100));

        
        jButtonHistoryUp.setIcon(new ImageIcon(cl.getResource("icons/uparrow.png")));
	jButtonHistoryUp.setMargin(new java.awt.Insets(0, 0, 0, 0));
        jButtonHistoryUp.setToolTipText("History Up");
        jButtonHistoryUp.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                historyUp();
            }
        });

        jPanelHistoryButtons.add(jButtonHistoryUp);

        jButtonHistoryDown.setIcon(new ImageIcon(cl.getResource("icons/downarrow.png")));
	jButtonHistoryDown.setMargin(new java.awt.Insets(0, 0, 0, 0));
        jButtonHistoryDown.setToolTipText("History Down");
        jButtonHistoryDown.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                historyDown();
            }
        });

        jPanelHistoryButtons.add(jButtonHistoryDown);

        jPanel2.add(jPanelHistoryButtons, java.awt.BorderLayout.EAST);

        jTextAreaInput.setMinimumSize(new java.awt.Dimension(20, 20));
        jTextAreaInput.setPreferredSize(new java.awt.Dimension(100, 20));
        //jTextAreaInput.setColumns(5);
        jTextAreaInput.setLineWrap(true);
        //jTextAreaInput.setRows(2);
        jTextAreaInput.setToolTipText("Enter your message here!");
        jTextAreaInput.setWrapStyleWord(true);
        jScrollPane2.setViewportView(jTextAreaInput);

        jPanel2.add(jScrollPane2, java.awt.BorderLayout.CENTER);

        jPanel1.add(jPanel2, java.awt.BorderLayout.SOUTH);

        jPanel4.setLayout(new java.awt.BorderLayout());

        jScrollPane4.setViewportView(jList2);

        jPanel4.add(jScrollPane4, java.awt.BorderLayout.CENTER);

        jPanel1.add(jPanel4, java.awt.BorderLayout.EAST);

        
        
        jScrollPane1.setViewportView(jEditorPaneMain);

        jPanel1.add(jScrollPane1, java.awt.BorderLayout.CENTER);

        getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);

        pack();

        // Init smiles
	url_smiles_smile = cl.getResource("icons/smiles/smile.png");
	url_smiles_wink = cl.getResource("icons/smiles/wink.png");
	url_smiles_unhappy = cl.getResource("icons/smiles/unhappy.png");
	url_smiles_oh = cl.getResource("icons/smiles/oh.png");
	url_smiles_tongue = cl.getResource("icons/smiles/tongue.png");
	url_smiles_biggrin = cl.getResource("icons/smiles/biggrin.png");
    }// </editor-fold>//GEN-END:initComponents

    // ############################## METHODS ##############################################

    /** Gets clicked URL and calls Browser */
    private void hyperlinkUpdateEvent(javax.swing.event.HyperlinkEvent evt) {
	if(evt.getEventType() == javax.swing.event.HyperlinkEvent.EventType.ACTIVATED)
            this.parent.openBrowser(evt.getDescription());
    }

    /** Clears the history */
    private void clearHistory() {
	this.member.clearMessages();
        this.jEditorPaneMain.setText("");	
    }

    /** Starts the send-file procedure */
    private void sendFile() {
        // Check if disconnected
        if(!this.member.isConnected()) {
	   javax.swing.JOptionPane.showMessageDialog(this, 
	       "The User is offline - you can't send a file!", 
	       "User is offline", 
	       javax.swing.JOptionPane.INFORMATION_MESSAGE);
	       return;
	}
       
        BASE64Handler b64h = new BASE64Handler(this);
	BASE64Handler.EncodedFileObject efo = b64h.getEncodedFile();
	
	if(efo != null) {
	   this.parent.theClient.sendMessage(efo.data, this.member.name, "file", efo.filename);
	   this.member.addMessage(ownMessageMarker + " " + "<i>---Sending File--- (" + efo.filename + ")</i>", "Sending File", "normal");
	   //this.member.hasNewMessage = false;
	   //this.updateWindow();
	} else {
	   // Show Error
	   javax.swing.JOptionPane.showMessageDialog(this, 
						      "Can't send file:\n" + b64h.getLastError(), 
						      "Can't send file", 
						      javax.swing.JOptionPane.ERROR_MESSAGE);
	}
    }

    /** Send the message */
    private void sendMessage() {
        // Check if disconnected
        if(!this.member.isConnected()) {
	   javax.swing.JOptionPane.showMessageDialog(this, 
	       "The User is offline - you can't send a message!", 
	       "User is offline", 
	       javax.swing.JOptionPane.INFORMATION_MESSAGE); 
	   
	   return;
	}

	String message = this.jTextAreaInput.getText();

	// Save in History
	this.historyList.add(message);
        this.historyPosition = 0;

	// Replace Whitespaces and HTML
        message = message.replaceAll("\n", "<br>");
        message = message.replaceAll("\r", "");

        if(message.length() > 0) {
            if(!this.member.type.equals(JTalkerParser.USER_TYPE_CHATROOM))
               this.member.addMessage(ownMessageMarker + " " + message, "my Message", "normal");
            
            //this.member.hasNewMessage = false;
            //this.updateWindow();

            if(message.startsWith("/")) {
                message = message.replaceFirst("/", "");
                this.parent.theClient.sendMessage(message, this.member.name, "command", null);
            } else
                this.parent.theClient.sendMessage(message, this.member.name);

            // Clear editor text
            this.jTextAreaInput.setText("");
        }
    }

    /** Back in the history */
    public void historyUp() {
       int tmpPos = this.historyList.size() - 1 - this.historyPosition;
       if(tmpPos < 0)
	  return;
       
       this.jTextAreaInput.setText((String)this.historyList.get(tmpPos));
       this.historyPosition++;
       if(this.historyPosition >= this.historyList.size())
	  this.historyPosition--;
    }

    /** Forward in the history */
    public void historyDown() {
       int tmpPos = this.historyList.size() - 1 - this.historyPosition;
       if(tmpPos < 0)
	  return;
       
       this.jTextAreaInput.setText((String)this.historyList.get(tmpPos));
       this.historyPosition--;
       if(this.historyPosition < 0) {
	  this.jTextAreaInput.setText("");
	  this.historyPosition = 0;
       }
    }

    /** Toggles the styles of view */
    public void toggleView() {
       this.textAreaStyle++;

       if(this.textAreaStyle > 2)
	  this.textAreaStyle = 0;

       if(this.textAreaStyle != 2) {
            this.jEditorPaneMain.setContentType("text/html; charset=UTF-8");
       } else
            this.jEditorPaneMain.setContentType("text/plain");

       this.updateWindow();
    }

    /** Updates the chat window */
    public void updateWindow() {
       String messageLines = "";

	// Overwrite text and background colors
        this.jEditorPaneMain.setBackground(Color.decode(this.parent.theClient.guiBgColor));
        this.jEditorPaneMain.setForeground(Color.decode(this.parent.theClient.guiTextColor));


       // Update only, if this window is visible!
       if(!this.isVisible())
	  return;

       // Check for received files
       /*if(this.member.saveBASE64Files()) {
	 this.member.addMessage("<i>---File received---</i>", "my Message", "normal");	
	 this.member.hasNewMessage = false;
       }*/

       //for( int i = this.member.numOfMessages() - 1; i >= 0; i-- ) {
       for( int i = 0; i < this.member.numOfMessages(); i++ ) {
	     String tmpMess = this.member.getMessage(i);

	     if(tmpMess != null) {
		// Get only Text-messages
		String tmpTime = this.member.getDate(i);		
		messageLines += this.makeTemplate(this.textAreaStyle,
						  this.member.short_name,
						  tmpTime,
						  tmpMess);
	     } 		
	   
            this.member.hasNewMessage = false;
       }       
	   
       messageLines = messageLines.replaceAll("<html>" , "");
       messageLines = messageLines.replaceAll("</html>" , "");
       
       if(this.textAreaStyle != 2) {
           // Make some replacement for HTML based Views
           // Replace smiles
           messageLines = messageLines.replaceAll(":-\\)","<img src=\"" + this.url_smiles_smile.toString() + "\">");
           messageLines = messageLines.replaceAll(":\\)","<img src=\"" + this.url_smiles_smile.toString() + "\">");
           messageLines = messageLines.replaceAll(";-\\)","<img src=\"" + this.url_smiles_wink.toString() + "\">");
           messageLines = messageLines.replaceAll(";\\)","<img src=\"" + this.url_smiles_wink.toString() + "\">");
           messageLines = messageLines.replaceAll(":-\\(","<img src=\"" + this.url_smiles_unhappy.toString() + "\">");
           messageLines = messageLines.replaceAll(":\\(","<img src=\"" + this.url_smiles_unhappy.toString() + "\">");
           messageLines = messageLines.replaceAll(":-O","<img src=\"" + this.url_smiles_oh.toString() + "\">");
           messageLines = messageLines.replaceAll(":-o","<img src=\"" + this.url_smiles_oh.toString() + "\">");
           messageLines = messageLines.replaceAll(":O","<img src=\"" + this.url_smiles_oh.toString() + "\">");
           messageLines = messageLines.replaceAll(":o","<img src=\"" + this.url_smiles_oh.toString() + "\">");
           messageLines = messageLines.replaceAll(":-P","<img src=\"" + this.url_smiles_tongue.toString() + "\">");
           messageLines = messageLines.replaceAll(":-p","<img src=\"" + this.url_smiles_tongue.toString() + "\">");
           messageLines = messageLines.replaceAll(":P","<img src=\"" + this.url_smiles_tongue.toString() + "\">");
           messageLines = messageLines.replaceAll(":p","<img src=\"" + this.url_smiles_tongue.toString() + "\">");
           messageLines = messageLines.replaceAll(":-D","<img src=\"" + this.url_smiles_biggrin.toString() + "\">");
           messageLines = messageLines.replaceAll(":-d","<img src=\"" + this.url_smiles_biggrin.toString() + "\">");
           messageLines = messageLines.replaceAll(":D","<img src=\"" + this.url_smiles_biggrin.toString() + "\">");
           messageLines = messageLines.replaceAll(":d","<img src=\"" + this.url_smiles_biggrin.toString() + "\">");

           // Parse URIs
           try { 
               // Replace email adresses
               Pattern p = Pattern.compile("[A-Za-z0-9\\.]+\\@[A-Za-z0-9\\.-]+");
               Matcher m = p.matcher(messageLines);
               StringBuffer sb = new StringBuffer();
               boolean wasReplaced = false;
               boolean result = m.find();
             
               while(result) {
                  m.appendReplacement(sb, "<a href=\"mailto:" + m.group() + "\">" + m.group() + "</a>");
                  wasReplaced = true;
                  result = m.find();
               }

               if(wasReplaced) {
                  m.appendTail(sb);
                  messageLines = sb.toString();
               }
	
               // Replace URLs
               p = Pattern.compile("([^\"])((http://|www\\.)[\\S&&[^<>;:\"]]+)");
               m = p.matcher(messageLines);
               sb = new StringBuffer();
               wasReplaced = false;
               result = m.find();
	 
               while(result) {
                  m.appendReplacement(sb, m.group(1) + "<a href=\"" + m.group(2) + "\">" + m.group(2) + "</a>");
                  wasReplaced = true;
                  result = m.find();
               }

               if(wasReplaced) {
		 m.appendTail(sb);
		 messageLines = sb.toString();
	      }
           } catch (Exception _e) {
               System.out.println("*** ERROR: while parsing URIs");
           }
       }     

       if(messageLines != null)
	 this.jEditorPaneMain.setText(messageLines);  
       
       //this.jEditorPaneMain.setCaretPosition(0);
       try {
           int num = this.jEditorPaneMain.getDocument().getLength();
           this.jEditorPaneMain.setCaretPosition(num);
           
           if(this.isChatRoom)
               this.checkChatroomUsers();

       } catch (Exception e) { } 
    }

    /** Formats the message with a special template */
    private String makeTemplate(int _style, String _userName, String _date, String _message) {
       String retVal = "";

       if(_style == 0) {
	  if(!_message.startsWith(ownMessageMarker)) {
	     retVal += "<table border=\"0\" width=\"100%\"><tr><td bgcolor=\"#cccccc\">" + 
			"<font color=\"black\"><b>" + _userName + "</b>" + 
			" (" + _date + ")" + 
			"</font></td></tr></table><font color=\"" + 
			parent.theClient.guiTextColor + "\">" +
			_message + "</font><br><br>";
	  } else {
	     retVal += "<font color=\"" + parent.theClient.guiTextColor + "\">" +
		       _message.replaceFirst(ownMessageMarker, 
		       "<table border=\"0\" width=\"100%\"><tr><td bgcolor=\"#ffff99\"><font color=\"black\"><b>" + 
		       this.parent.theClient.userName + "</b> (" + 
		       _date + ")</font></td></tr></table>");
	     retVal += "</font><br><br>";
	  }
       }
       else if(_style == 1) {
	  // Only for Chatroom - no chatroom name
	  String tmpUserName = _userName;
	  
	  if(this.member.type.equals(JTalkerParser.USER_TYPE_CHATROOM))
	     tmpUserName = "";
	     
	  if(!_message.startsWith(ownMessageMarker)) {
	     retVal += "<font color=\"" + parent.theClient.guiTextColor + "\">" + 
			"<b>(" + _date + ") " +	tmpUserName +
			":</b> " + _message + "</font><br>";
	  } else {
	     if(!this.member.type.equals(JTalkerParser.USER_TYPE_CHATROOM))
		tmpUserName = this.parent.theClient.userName;
	     
	     retVal += "<font color=\"" + parent.theClient.guiTextColor + "\">" +
		       _message.replaceFirst(ownMessageMarker, 
					     "<b>(" + _date + ") " + tmpUserName + ":</b> ");
	     retVal += "</font><br>";
	  }
       }
       else if(_style == 2) {
          String tmpUserName = _userName;
	  
	  if(this.member.type.equals(JTalkerParser.USER_TYPE_CHATROOM))
	     tmpUserName = "";
          
           if(!_message.startsWith(ownMessageMarker)) {
	     retVal += "\n(" + _date + ") " + tmpUserName + ": " + _message;
	   } else {
	     if(!this.member.type.equals(JTalkerParser.USER_TYPE_CHATROOM))
		tmpUserName = this.parent.theClient.userName;
	     
	     retVal += _message.replaceFirst(ownMessageMarker, "\n(" + _date + ") " + tmpUserName + ": ");
	  }
       }

       return retVal;
    }

    /** Checks for users in a chatroom */
    private void checkChatroomUsers() {
       if(!this.isChatRoom)
           return;

       this.parent.theClient.sendMessage("std::getChatRoomUsers(\"" + this.member.short_name + "\")", null, "command", null, "getchatusers01");
    }
    
    /** A command answer will be send to us from the server using this method 
     *  @return true, if we handle this command */
    public boolean setCommandAnswer(String _id, String _from, String _content) {
        if(_id.equals("getchatusers01")) {
           String lastResponse = _content;

           if(lastResponse == null)
               return true;

           this.chatRoomUsers = lastResponse.split(";;");

           if(this.memberListModel != null)
               this.memberListModel.propertyChanged();

           return true;

        } else if(_id.equals("addchatuser01") || _id.equals("rmchatuser01")) {
           this.checkChatroomUsers();
           return true;
        }

        return false;
    }
    
    
    /** Inits all Keyboard Shortcuts */
    private void initShortcuts() {
        InputMap keyMap = new ComponentInputMap(this.jButtonSend_3);
        keyMap.put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_ENTER, java.awt.event.InputEvent.CTRL_MASK), "action");

        ActionMap actionMap = new ActionMapUIResource();
        actionMap.put("action", this);

        SwingUtilities.replaceUIActionMap(this.jButtonSend_3, actionMap);
        SwingUtilities.replaceUIInputMap(this.jButtonSend_3, JComponent.WHEN_IN_FOCUSED_WINDOW, keyMap);
    }

    /** Exit the Application */
    private void exitForm(java.awt.event.WindowEvent evt) {        
        //this.ucu.terminate = true;
        //this.ut.terminate = true;
        this.dispose();
    }   
   
    // Interface functions for Action
    public Object 	getValue(String key) {return null;}
    public void 	putValue(String key, Object value) {}    
    
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButtonClear;
    private javax.swing.JButton jButtonHistoryDown;
    private javax.swing.JButton jButtonHistoryUp;
    private javax.swing.JButton jButtonSendFile;
    private javax.swing.JButton jButtonSend_3;
    private javax.swing.JButton jButtonView;
    private javax.swing.JTextArea jTextAreaInput;
    //private javax.swing.JEditorPane jTextAreaInput;
    private javax.swing.JEditorPane jEditorPaneMain;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JList jList2;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanelHistoryButtons;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane4;
    private javax.swing.JToolBar jToolBarButtons;
    // End of variables declaration//GEN-END:variables
    //
    // Smiles
    private java.net.URL url_smiles_smile;
    private java.net.URL url_smiles_wink;
    private java.net.URL url_smiles_unhappy;
    private java.net.URL url_smiles_oh;
    private java.net.URL url_smiles_tongue;
    private java.net.URL url_smiles_biggrin;
    
    /** Class for asynchron updating the Window */
    public class UpdateTimer extends Thread {
       private JTalkerFrontChat parent = null;
       public boolean terminate = false;
       
       public UpdateTimer (JTalkerFrontChat _parent) {
	  this.parent = _parent;
       }
       
       public void run() {
	  boolean firstRun = true;
	  while(!terminate) {	     
	     try {
		this.sleep(300);
	     
                 if(firstRun || this.parent.member.hasNewMessage) {
                   firstRun = false;
                   
                   // Check for received files
                   if(this.parent.isVisible()) {
                       this.parent.updateWindow();		

                       if(this.parent.member.saveBASE64Files()) {
                         this.parent.member.addMessage("<i>---File received---</i>", "my Message", "normal");	
                       }
                   }
                   
                }
	     } catch (Exception e) {} 
	  }	  
       }
    }

    /** Model for the JList with all in a Chatroom */
    // TODO: Implement this in JTalkerMember! or? ;-)
    public class MemberListModel implements javax.swing.ListModel {      
       private ListDataListener myDataListener = null;
       // TODO: Replace this by a real size!
       
       public MemberListModel() {}   

       // Notify a Change - call this methode if the data-source has changed
       public void propertyChanged() {
          int tmpLength = 0;
          if(chatRoomUsers != null)
              tmpLength = chatRoomUsers.length;
          
	  this.myDataListener.contentsChanged(new ListDataEvent(this, 
							       ListDataEvent.CONTENTS_CHANGED, 
							       tmpLength, 
							       0));
       }

       // List Model Listener
       public void addListDataListener(ListDataListener _l) {
	  this.myDataListener = _l;
       }
       public Object getElementAt(int _index) {
	  return chatRoomUsers[_index];
       }
       public int getSize() {
           if(chatRoomUsers != null)
               return chatRoomUsers.length;
           else
               return 0;
       }
       public void removeListDataListener(ListDataListener _l) {}    
    }
    
}
